﻿//using System;
//using System.Diagnostics;
//using System.IO.Compression;
//using System.Net.Http;
//using System.Reflection;
//using System.Runtime.Loader;
//using System.Threading;
//using System.Threading.Tasks;
//using Microsoft.Extensions.DependencyInjection;
//using Microsoft.Extensions.Hosting;
//using Microsoft.Extensions.Logging;
//using Microsoft.Extensions.Options;
//using Newtonsoft.Json;

//namespace PasteCodeTaskBase
//{
//    public class TaskRemoteService : IHostedService
//    {
//        private TaskChannelHelper _channelHelper;
//        private ILogger<TaskRemoteService> _logger;
//        private IServiceProvider _serviceProvider;
//        private IHttpClientFactory _httpclientFactory;
//        private TaskNodeConfig _config;
//        //private AssemblyLoadContext context;
//        private JsonSerializerSettings setting;
//        //private SemaphoreSlim _semaphore;

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="channelHelper"></param>
//        /// <param name="logger"></param>
//        /// <param name="serviceProvider"></param>
//        /// <param name="httpclientFactory"></param>
//        /// <param name="config"></param>
//        public TaskRemoteService(TaskChannelHelper channelHelper,
//            ILogger<TaskRemoteService> logger,
//            IServiceProvider serviceProvider,
//            IHttpClientFactory httpclientFactory,
//            IOptions<TaskNodeConfig> config)
//        {
//            _channelHelper = channelHelper;
//            _logger = logger;
//            _serviceProvider = serviceProvider;
//            _httpclientFactory = httpclientFactory;
//            _config = config.Value;
//            //context = new AssemblyLoadContext();
//            //_semaphore = new SemaphoreSlim(_config.MaxThreadCount);

//            #region 配置序列号格式
//            setting = new Newtonsoft.Json.JsonSerializerSettings();
//            //日期格式化
//            setting.DateFormatString = "yyyy-MM-dd HH:mm:ss";
//            //是否格式化换行便于阅读
//            //setting.Formatting = Newtonsoft.Json.Formatting.Indented;
//            //首字母小写
//            setting.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
//            #endregion
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="cancellationToken"></param>
//        /// <returns></returns>
//        public Task StartAsync(CancellationToken cancellationToken)
//        {
//            Console.WriteLine($"{DateTime.Now} Remote Tick HostedService Start!");
//            JoinMaster();
//            ReadChannel();
//            return Task.CompletedTask;
//        }

//        /// <summary>
//        /// 检查任务
//        /// </summary>
//        private async void ReadChannel()
//        {
//            try
//            {
//                var _info = await _channelHelper.Task.Reader.ReadAsync();
//                if (_info != null && _info != default)
//                {
//                    var info = _info;
//                    var stop = new Stopwatch();
//                    stop.Start();
//                    TaskCallBackDto? calldto = default;
//                    try
//                    {
//                        //执行任务
//                        //Console.WriteLine($"read task from channel {Newtonsoft.Json.JsonConvert.SerializeObject(info, setting)}");

//                        if (!String.IsNullOrEmpty(info.AssemblyZip))
//                        {
//                            //加载外在的
//                            _logger.LogInformation($"Load DLL Assembly from Url:{info.AssemblyZip}");
//                            var path = $"/app/wwwroot/upload/{info.Id}/{info.FileVersion}";
//                            if (!System.IO.Directory.Exists(path))
//                            {
//                                System.IO.Directory.CreateDirectory(path);
//                            }
//                            var savepath = $"{path}/{info.Assembly}";
//                            var dllpath = $"/app/wwwroot/upload/{info.Id}/{info.FileVersion}/{info.Assembly}.dll";
//                            var zippath = $"/app/wwwroot/upload/{info.Id}/{info.FileVersion}/{info.Assembly}.zip";
//                            if (!System.IO.File.Exists(dllpath))
//                            {
//                                _logger.LogInformation($"Begin to download:{zippath} from url:{info.AssemblyZip}");
//                                using var client = _httpclientFactory.CreateClient();
//                                var array = await client.GetByteArrayAsync(info.AssemblyZip);
//                                using var fs = new System.IO.FileStream(zippath, System.IO.FileMode.Create);
//                                fs.Write(array, 0, array.Length);
//                                fs.Close();
//                                fs.Dispose();
//                                ZipFile.ExtractToDirectory(zippath, savepath, true);
//                                System.IO.File.Delete(zippath);
//                            }

//                            var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(System.IO.Path.GetFileNameWithoutExtension(dllpath)));
//                            Type type = assembly.GetType(info.Assembly, true, true);
//                            var task = Activator.CreateInstance(type) as IPasteCodeTaskBase;
//                            if (task != null)
//                            {
//                                calldto = await task.Work(info);
//                            }

//                        }
//                        else
//                        {
//                            //加载内置的
//                            var _scope = _serviceProvider.CreateScope();
//                            var tasks = _scope.ServiceProvider.GetServices<IPasteCodeTaskBase>();
//                            foreach (var item in tasks)
//                            {
//                                var _t = item.GetType();
//                                if (_t.Name == info.Assembly)
//                                {
//                                    calldto = await item.Work(info);
//                                    break;
//                                }
//                            }
//                        }
//                        stop.Stop();
//                        if (calldto != null && calldto != default)
//                        {
//                            calldto.logid = info.TaskLogId;
//                            calldto.taskid = info.Id;
//                            calldto.nodeid = info.NodeId;
//                            calldto.duration = (int)stop.Elapsed.TotalSeconds;
//                            //calldto.nodeid = 
//                        }
//                        else
//                        {
//                            calldto = new TaskCallBackDto();
//                            calldto.code = 500;
//                            calldto.logid = info.TaskLogId;
//                            calldto.taskid = info.Id;
//                            calldto.message = $"{info.Assembly} Not Found";
//                            calldto.duration = (int)stop.Elapsed.TotalSeconds;
//                        }
//                        await UpdateCallBack(calldto);
//                    }
//                    catch (Exception eload)
//                    {
//                        _logger.LogError(eload.Message);
//                        //回调
//                        stop.Stop();

//                        calldto = new TaskCallBackDto();
//                        calldto.taskid = info.Id;
//                        calldto.logid = info.TaskLogId;
//                        calldto.nodeid = info.NodeId;
//                        calldto.code = 500;
//                        calldto.message = eload.Message;
//                        calldto.duration = (int)stop.Elapsed.TotalSeconds;
//                        await UpdateCallBack(calldto);
//                    }

//                }
//            }
//            catch (Exception exl)
//            {
//                _logger.LogError(exl.Message);
//                await Task.Delay(100);
//            }
//            finally
//            {
//                ReadChannel();
//            }
//        }

//        /// <summary>
//        /// 任务回调 告知任务中心，任务执行的结果，默认为成功
//        /// </summary>
//        /// <param name="info"></param>
//        /// <returns></returns>
//        private async Task<bool> UpdateCallBack(TaskCallBackDto info)
//        {
//            if (info != null)
//            {
//                if (!String.IsNullOrEmpty(_config.MasterUrl) && !String.IsNullOrEmpty(_config.JoinToken))
//                {
//                    try
//                    {
//                        var postdata = (JsonConvert.SerializeObject(info, setting));
//                        using HttpContent httpcontent = new StringContent(postdata);
//                        var timestmp = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();
//                        var headtoken = ($"{timestmp}_0_{_config.JoinToken}".ToMd5Lower());
//                        var xtoken = $"{timestmp}_0_{headtoken}";//服务端需要根据游戏ID获取 密钥，否则无法验证xtoken是否合法
//                        httpcontent.Headers.Add("xtoken", xtoken);
//                        httpcontent.Headers.Add("stoken", _config.PublicToken);
//                        httpcontent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json;charset=utf-8");
//                        var client = _httpclientFactory.CreateClient();
//                        var url = $"{_config.MasterUrl}api/task/callback";
//                        var response = await client.PostAsync(url, httpcontent);

//                        if (!response.IsSuccessStatusCode)
//                        {
//                            _logger.LogError($"Task CallBack Upload Error! Code:{response.StatusCode} Response:{await response.Content.ReadAsStringAsync()}");
//                        }
//                    }
//                    catch (Exception exl)
//                    {
//                        _logger.LogWarning("task callback throw exception:");
//                        _logger.LogError(exl.Message);
//                    }
//                }
//                else
//                {
//                    _logger.LogError("配置文件错误 MasterUrl 或者 JoinToken 不能为空！");
//                }
//            }
//            else
//            {
//                _logger.LogError("UpdateCallBack Query info is null!");
//            }
//            return true;
//        }

//        //加入主调度中心
//        private void JoinMaster()
//        {
//            if (!String.IsNullOrEmpty(_config.MasterUrl) && !String.IsNullOrEmpty(_config.Url))
//            {
//                var timer = new System.Timers.Timer();
//                timer.AutoReset = false;
//                timer.Interval = 5000;
//                timer.Elapsed += Timer_Elapsed;
//                timer.Start();
//            }
//            else
//            {
//                _logger.LogWarning("if is client side check appsettings.json TaskNodeConfig!");
//            }
//        }

//        /// <summary>
//        /// 加入到调度中心
//        /// </summary>
//        private int trylinktime = 0;
//        /// <summary>
//        /// 是否加入到服务中了
//        /// </summary>
//        private bool _joined = false;
//        private async void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
//        {
//            //Console.WriteLine($"{DateTime.Now} Timer_Elapsed ====== ------ -=-=-=-");
//            var timer = (System.Timers.Timer)sender;
//            if (!String.IsNullOrEmpty(_config.MasterUrl) && !String.IsNullOrEmpty(_config.Url))
//            {

//                if (String.IsNullOrEmpty(_config.JoinToken))
//                {
//                    _config.JoinToken = Guid.NewGuid().ToString().Replace("-", "").ToLower();
//                }

//                trylinktime++;
//                if (trylinktime > 60)
//                {
//                    trylinktime = 60;
//                }

//                var join = new JoinInfo()
//                {
//                    Group = _config.Group,
//                    JoinToken = _config.JoinToken,
//                    Url = _config.Url,
//                    ClientCode = _config.ClientCode
//                };

//                try
//                {

//                    //Console.WriteLine($"{DateTime.Now} begin to join master!");
//                    _logger.LogWarning($"begin to join {_config.MasterUrl} timer master!");
//                    var postdata = (Newtonsoft.Json.JsonConvert.SerializeObject(join, setting));
//                    using HttpContent httpcontent = new StringContent(postdata);
//                    var timestmp = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();
//                    var headtoken = ($"{timestmp}_0_{_config.JoinToken}");
//                    var xtoken = $"{timestmp}_0_{headtoken}";//服务端需要根据游戏ID获取 密钥，否则无法验证xtoken是否合法
//                    httpcontent.Headers.Add("xtoken", xtoken);
//                    httpcontent.Headers.Add("stoken", _config.PublicToken);
//                    httpcontent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json;charset=utf-8");
//                    var client = _httpclientFactory.CreateClient();
//                    var url = $"{_config.MasterUrl}api/task/join";
//                    var response = await client.PostAsync(url, httpcontent);

//                    if (!response.IsSuccessStatusCode)
//                    {
//                        timer.Interval = trylinktime * 5000;
//                        timer.Start();
//                    }
//                    else
//                    {
//                        _joined = true;
//                        _logger.LogWarning($"当前客户端:{_config.Url} 加入到任务主服务:{_config.MasterUrl} 成功! join:token:{_config.JoinToken}");
//                        var one = Newtonsoft.Json.JsonConvert.DeserializeObject<JoinInfo>(await response.Content.ReadAsStringAsync());
//                        if (one != null)
//                        {
//                            _config.JoinToken = one.JoinToken;
//                        }
//                    }
//                }
//                catch (Exception exl)
//                {
//                    _logger.LogError(exl.Message);
//                    timer.Interval = trylinktime * 5000;
//                    timer.Start();
//                }

//            }
//            else
//            {
//                _logger.LogError($"TaskNodeConfig 配置错误！ JoinToken:{_config.JoinToken} MasterUrl:{_config.MasterUrl}!");
//                timer.Interval = 5000;
//                timer.Start();
//            }
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="cancellationToken"></param>
//        /// <returns></returns>
//        public async Task StopAsync(CancellationToken cancellationToken)
//        {

//            //离开集群... .. .
//            if (_joined)
//            {
//                if (!String.IsNullOrEmpty(_config.MasterUrl) && !String.IsNullOrEmpty(_config.JoinToken))
//                {
//                    var join = new JoinInfo()
//                    {
//                        Group = _config.Group,
//                        JoinToken = _config.JoinToken,
//                        Url = _config.Url
//                    };

//                    try
//                    {

//                        var postdata = (Newtonsoft.Json.JsonConvert.SerializeObject(join, setting));
//                        using HttpContent httpcontent = new StringContent(postdata);
//                        var timestmp = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();
//                        var headtoken = ($"{timestmp}_0_{_config.JoinToken}");
//                        var xtoken = $"{timestmp}_0_{headtoken}";//服务端需要根据游戏ID获取 密钥，否则无法验证xtoken是否合法
//                        httpcontent.Headers.Add("xtoken", xtoken);
//                        httpcontent.Headers.Add("stoken", _config.PublicToken);
//                        httpcontent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json;charset=utf-8");
//                        var client = _httpclientFactory.CreateClient();
//                        var url = $"{_config.MasterUrl}api/task/leave";
//                        var response = await client.PostAsync(url, httpcontent);
//                    }
//                    catch (Exception exl)
//                    {
//                        _logger.LogError(exl.Message);
//                    }
//                }
//            }

//            // return Task.CompletedTask;
//        }
//    }
//}
